package com.hz.monitoring.module.hardware.socket.ifwl_gprs_v2.server;

import com.hz.monitoring.module.hardware.service.mcu_tenant_resource.McuTenantResourceService;
import com.hz.monitoring.module.hardware.service.monitoring_data.MonitoringDataService;
import com.hz.monitoring.module.hardware.service.monitoring_warning_log.MonitoringWarningLogService;
import com.hz.monitoring.module.hardware.service.sensor_tenant_resource.SensorTenantResourceService;
import com.hz.monitoring.module.hardware.service.warning_contact.WarningContactService;
import com.hz.monitoring.module.hardware.socket.ifwl_gprs_v2.handler.DecoderHandler;
import com.hz.monitoring.module.hardware.socket.ifwl_gprs_v2.handler.EncoderHandler;
import com.hz.monitoring.module.hardware.socket.ifwl_gprs_v2.handler.HearBeatHandler;
import com.hz.monitoring.module.hardware.socket.ifwl_gprs_v2.handler.NettyServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/***
 * 分布式GPRS节点产品型号：IFWL-GPRS-V2.00硬件版本：V2.01固件版本：V2.07生产批次：C2021081102-1151
 */

@Component
public class NettyServer {
    /**
     * 日志
     */
    private Logger log = LoggerFactory.getLogger(getClass());

    @Value("${netty.ifwl_gprs_v2.port}")
    private int port;

    @Resource
    private  McuTenantResourceService mcuTenantResourceService;

    @Resource
    private  SensorTenantResourceService sensorTenantResourceService;

    @Resource
    private  MonitoringDataService monitoringDataService;

    @Resource
    private  WarningContactService warningContactService;

    @Resource
    private  MonitoringWarningLogService monitoringWarningLogService;

    //EventLoopGroup是用来处理IO操作的多线程事件循环器
    //负责接收客户端连接线程
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    //负责处理客户端i/o事件、task任务、监听任务组
    EventLoopGroup workerGroup = new NioEventLoopGroup();

    ServerBootstrap serverBootstrap = new ServerBootstrap();

    private Channel channel = null;

    /**
     * 启动服务器方法
     */
   // @PostConstruct //交给启动项统一管理，不使用注解启动
    public void init() {
        try {
            serverBootstrap.group(bossGroup, workerGroup);//绑定线程池
            //配置 Channel
            serverBootstrap.channel(NioServerSocketChannel.class);

            // 标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 128);//服务端接受连接的队列长度，如果队列已满，客户端连接将被拒绝
            serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
            //socketchannel的设置,关闭延迟发送
            serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);
            //保持长连接，2小时无数据激活心跳机制
            serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            //使用匿名内部类的形式初始化通道对象
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    //给pipeline管道设置处理器
                    pipeline.addLast("bdeCoder", new DecoderHandler());
                    pipeline.addLast("benCoder", new EncoderHandler());
                    //读写超时设置
                    pipeline.addLast(new IdleStateHandler(300, 300, 500, TimeUnit.SECONDS));
                    //心跳机制处理器
                    pipeline.addLast(new HearBeatHandler());
                    pipeline.addLast(new NettyServerHandler(mcuTenantResourceService, sensorTenantResourceService, monitoringDataService, warningContactService, monitoringWarningLogService));
                }
            });//给workerGroup的EventLoop对应的管道设置处理器
            // 绑定端口,开始接收进来的连接
            //绑定服务端口监听
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            channel = channelFuture.channel();
            log.info("IFWL-GPRS-V2.00服务启动: [port:" + port + "]");
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("IFWL-GPRS-V2.00 服务启动异常-" + e.getMessage());
        } finally {
            //关闭事件流组
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }


    /**
     * 停止服务
     */
    public void destroy() {
        log.info("Shutdown IFWL-GPRS-V2.00 Server...");
        if (channel != null) {
            channel.close();
        }
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
        log.info("Shutdown IFWL-GPRS-V2.00 Server Success!");
    }
}
